﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using Microsoft.MediaCenter.UI;
using MyMoviesBrowserLibrary.MyMovies;

namespace MyMoviesBrowser
{
    class MyMoviesData : MovieDataInterface
    {
        List<string> parentalRatings = new List<string>(new string[] { "", "Not Rated", "G", "PG", "PG-13", "NC-17", "R" });
        private MyMoviesDataContext ctx;
        private string serverName;
        public MyMoviesData()
        {
            ctx = MyMoviesBusiness.GetNewMyMoviesDataContext();
            serverName = MyMoviesBrowserLibrary.Settings.Default.MyMoviesServerName;
        }

        #region MovieDataInterface Members

        public ArrayListDataSet CreateFilters(IModelItemOwner owner)
        {
            ArrayListDataSet list = new ArrayListDataSet(owner);

            // Create the unfiltered "All" filter
            ModelItem filter = new Filter(owner, Resources.GroupBy_Title, 0);
            list.Add(filter);

            filter = new Filter(owner, Resources.GroupBy_LastAdded, 5);
            list.Add(filter);

            filter = new Filter(owner, Resources.FilterBy_NotWatched, 7);
            list.Add(filter);

            filter = new Filter(owner, Resources.FilterBy_Rating, 8);
            list.Add(filter);


            filter = new Filter(owner, Resources.GroupBy_MPAARating, 2);
            list.Add(filter);

            filter = new Filter(owner, Resources.GroupBy_Genre, 3);
            list.Add(filter);

            filter = new Filter(owner, Resources.GroupBy_Release_Date, 1);
            list.Add(filter);

            return list;
        }

        public void FilterContent(MovieGallery page,int filterId)
        {
            switch (filterId)
            {
                case 1:
                    var r2 = page.Movies.OrderBy(m => m.ReleaseDate).ThenBy(m => m.Title).GroupBy(t => t.ReleaseDate.Value.Date);
                    foreach (var result in r2)
                    {
                        bool first = true;
                        foreach (var m in result)
                        {
                            page.Content.Add(page.CreateGalleryItem(m, m.ReleaseDate.HasValue ? m.ReleaseDate.Value.ToString("MMM d, yyyy") : "", first));
                            first = false;
                        }
                    }
                    break;
                case 2:
                    var r3 = page.Movies.OrderBy(m => m.Rating).ThenBy(m => m.Title).GroupBy(t => t.Rating);
                    foreach (var result in r3)
                    {
                        bool first = true;
                        foreach (var m in result)
                        {
                            page.Content.Add(page.CreateGalleryItem(m, m.Rating, first));
                            first = false;
                        }
                    }
                    break;
                case 3:
                    var r4 = page.Movies.OrderBy(m => m.Genre).ThenBy(m => m.Title).GroupBy(t => t.Genre);
                    foreach (var result in r4)
                    {
                        bool first = true;
                        foreach (var m in result)
                        {
                            page.Content.Add(page.CreateGalleryItem(m, m.Genre, first));
                            first = false;
                        }
                    }
                    break;
                case 4:
                    var r5 = page.Movies.OrderBy(m => m.Studio).ThenBy(m => m.Title).GroupBy(t => t.Studio);
                    foreach (var result in r5)
                    {
                        bool first = true;
                        foreach (var m in result)
                        {
                            page.Content.Add(page.CreateGalleryItem(m, m.Studio, first));
                            first = false;
                        }
                    }
                    break;
                case 5:
                    var r7 = page.Movies.OrderByDescending(m => m.MovieTitle.datAdded).ThenBy(m => m.Title).GroupBy(m => m.MovieTitle.datAdded.Value.Date);
                    foreach (var result in r7)
                    {
                        bool first = true;
                        foreach (var m in result)
                        {
                            page.Content.Add(page.CreateGalleryItem(m, m.MovieTitle.datAdded.HasValue ? m.MovieTitle.datAdded.Value.ToString("MMM d, yyyy") : "", first));
                            first = false;
                        }
                    }
                    break;
                case 6:
                    var r8 = page.Movies.Where(m => m.MovieTitle.Watched).OrderBy(m => m.SortTitle);
                    foreach (MyMovie m in r8)
                        page.Content.Add(page.CreateGalleryItem(m, "", false));
                    break;
                case 7:
                    var r9 = page.Movies.Where(m => !m.MovieTitle.Watched).OrderBy(m => m.SortTitle);
                    foreach (MyMovie m in r9)
                        page.Content.Add(page.CreateGalleryItem(m, "", false));
                    break;
                case 8:
                    var r10 = page.Movies.OrderByDescending(m => m.MovieTitle.intRating).ThenBy(m => m.Title).GroupBy(t => t.MovieTitle.intRating);
                    foreach (var result in r10)
                    {
                        bool first = true;
                        foreach (var m in result)
                        {
                            page.Content.Add(page.CreateGalleryItem(m, m.MovieTitle.intRating.HasValue ? m.MovieTitle.intRating.Value.ToString() : "", first));
                            first = false;
                        }
                    }
                    break;
                default:
                    var r6 = page.Movies.OrderBy(m => m.SortTitle);
                    foreach (MyMovie m in r6)
                        page.Content.Add(page.CreateGalleryItem(m, "", false));
                    break;
            }
        }

        public void AddCommands(MovieMenu menu)
        {
            menu.AddCommand("All Titles", 0);
            menu.AddCommand("Categories", 1);
            menu.AddCommand("Genres", 2);
            menu.AddCommand("MPAA Ratings", 3);
            menu.AddCommand("Ratings", 4);
            menu.AddCommand("Series", 5);
        }

        public void SelectMenuOption(MovieMenu menu, int? menuOption)
        {
            int count = 0;
            switch (menuOption)
            {
                case 1:
                    Table<Category> cats = ctx.GetTable<Category>();
                    Table<TitleCategory> titlecats = ctx.GetTable<TitleCategory>();
                    var tc = from cat in cats
                             join titleCat in titlecats on cat.intId equals titleCat.intCategory
                             select new { Category = cat, TitleCategory = titleCat };
                    var cats2 = tc.Select(g1 => g1.Category).Distinct().OrderBy(g1 => g1.nvcName);
                    foreach (Category c in cats2)
                    {
                        menu.AddCommand(string.Format("{0} ({1})", c.nvcName, tc.Select(q3 => q3.TitleCategory).Count(q2 => q2.intCategory == c.intId)), c.intId);
                    }
                    break;
                case 2:
                    Table<Genre> genres = ctx.GetTable<Genre>();
                    Table<TitleGenre> titleGenres = ctx.GetTable<TitleGenre>();
                    var qg = from genre in genres
                             join titleGenre in titleGenres on genre.intId equals titleGenre.intGenre
                             orderby genre.nvcName
                             select new { Genre = genre, TitleGenre = titleGenre };
                    var genres2 = qg.Select(g1 => g1.Genre).Distinct();
                    foreach (Genre c in genres2)
                    {
                        menu.AddCommand(string.Format("{0} ({1})", c.nvcName, qg.Select(q3 => q3.TitleGenre).Count(q2 => q2.intGenre == c.intId)), c.intId);
                    }
                    break;
                case 3:
                    var mpaaRatings = ctx.Titles.Select(t => t.intCertification);
                    count = mpaaRatings.Where(r => !r.HasValue).Count();
                    if (count > 0)
                        menu.AddCommand(string.Format("No Rating ({0})", count), null);

                    for (int x = 1; x < parentalRatings.Count; x++)
                    {
                        count = mpaaRatings.Where(r => r.Value == x).Count();
                        if (count > 0)
                            menu.AddCommand(string.Format("{0} ({1})", parentalRatings[x], count), x);
                    }
                    break;
                case 4:

                    var ratings = ctx.Titles.Select(t => t.intRating);
                    count = ratings.Where(r => !r.HasValue).Count();
                    if (count > 0)
                        menu.AddCommand(string.Format("No Rating ({0})", count), null);

                    foreach (int? rating in ratings.Distinct().OrderByDescending(r => r.Value))
                    {
                        count = ratings.Where(r => r.Value == rating).Count();
                        if (count > 0)
                            menu.AddCommand(string.Format("{0} ({1})", rating, count), rating);
                    }
                    break;
                case 5:
                    Table<TitleSeries> seriesTable = ctx.GetTable<TitleSeries>();
                    Table<Title> titleTable = ctx.GetTable<Title>();

                    var titleSeries = from series in seriesTable
                                      join title in titleTable on series.intTitle equals title.intId
                                      join titles in titleTable on series.intTitleSerie equals titles.intId
                                      orderby title.SortTitle
                                      select new { Series = series, Title = title, Titles = titles };
                    var titleSeries2 = titleSeries.Select(g1 => g1.Title).Distinct();

                    foreach (var title in titleSeries2)
                    {
                        count = titleSeries.Where(r => r.Series.intTitle == title.intId).Count();
                        TitleSeries ts = titleSeries.FirstOrDefault(r => r.Series.intTitle == title.intId).Series;
                        if (ts != null && !ts.bitExcludeHolder)
                            count++;
                        menu.AddCommand(string.Format("{0} ({1})", title.OriginalTitle, count), title.intId);
                    }
                    break;
                default:
                    break;
            }
        }

        public void SelectionInvoked(MovieMenu menu, object data)
        {
            int? id = (int?)data;


            if (menu.chosenOption.HasValue)
            {
                List<MyMovie> moviesList = new List<MyMovie>();
                switch (menu.chosenOption.Value)
                {
                    case 1:
                        Category cat = ctx.Categories.SingleOrDefault(c => c.intId == id);
                        var intTitles = ctx.TitleCategories.Where(t => t.intCategory == cat.intId).Select(t => t.intTitle);
                        moviesList = (from m in ctx.Titles
                                      where intTitles.Contains(m.intId)
                                      orderby m.SortTitle
                                      select new MyMovie(m, serverName)).ToList();
                        break;
                    case 2:
                        Genre genre = ctx.Genres.SingleOrDefault(c => c.intId == id);
                        var intTitles2 = ctx.TitleGenres.Where(t => t.intGenre == genre.intId).Select(t => t.intTitle);
                        moviesList = (from m in ctx.Titles
                                      where intTitles2.Contains(m.intId)
                                      orderby m.SortTitle
                                      select new MyMovie(m, serverName)).ToList();
                        break;
                    case 3:
                        moviesList = (from m in ctx.Titles
                                      where m.intCertification == id
                                      orderby m.SortTitle
                                      select new MyMovie(m, serverName)).ToList();
                        break;
                    case 4:

                        moviesList = (from m in ctx.Titles
                                      where m.intRating == id
                                      orderby m.SortTitle
                                      select new MyMovie(m, serverName)).ToList();
                        break;
                    case 5:

                        var q = ctx.Titles.Where(t => t.intId == id);
                        if (q.Count() > 0)
                        {
                            var item = q.First();
                            var itemIds = ctx.TitleSeries.Where(t => t.intTitle == item.intId).Select(t => t.intTitleSerie).ToList();
                            itemIds.Add(item.intId);

                            moviesList = (from m in ctx.Titles
                                          where itemIds.Contains(m.intId)
                                          orderby m.SortTitle
                                          select new MyMovie(m, serverName)).ToList();
                        }
                        break;
                    default:
                        break;
                }
                Application.Current.GoToGalleryPage(new MovieGallery(moviesList));
                return;
            }
            else
            {
                if (id == 0)
                {
                    var movies = from m in ctx.Titles
                                 orderby m.SortTitle
                                 select new MyMovie(m, serverName);

                    Application.Current.GoToGalleryPage(new MovieGallery(movies.ToList()));
                    return;
                }
                Application.Current.GoToMovieMenu(new MovieMenu((int?)id));
            }
        }

        #endregion
    }
}
